#include <iostream>
#include <fstream>
#include <cstring>
#include <thread>
#include <map>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include "ikcp.h"

#define KCP_MTU 1400
#define LOCAL_PORT 5001
#define CONTROL_MAGIC 0xAABBCCDD
#define DATA_MAGIC 0x11223344

//获取毫秒时间
static inline uint32_t ikcp_getms() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

class KCPReceiver {
public:
//创建udp监听
    KCPReceiver() {
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        struct sockaddr_in local_addr;
        local_addr.sin_family = AF_INET;
        local_addr.sin_port = htons(LOCAL_PORT);
        local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
        printf("创建udp监听\n");
        running = true;
    }

    void start() {
        receiveThread = std::thread(&KCPReceiver::receiveUDP, this);
    }

    void stop() {
        running = false;
        receiveThread.join();
        for (auto& pair : convThreads) {
            pair.second.join();
        }
        for (auto& pair : convKCP) {
            ikcp_release(pair.second);
        }
    }

private:
    void receiveUDP() {
        char buffer[KCP_MTU + 16];
        struct sockaddr_in src_addr;
        socklen_t addr_len = sizeof(src_addr);
        //如果在运行 就循环 否则退出
        printf("进入receiveUDP循环");
        while (running) {
            int recv_len = recvfrom(sockfd, buffer, KCP_MTU + 16, 0, (struct sockaddr*)&src_addr, &addr_len);
            if (recv_len > 0) {
                printf("收到数据");
                uint32_t magic = *(uint32_t*)buffer;
                if (magic == CONTROL_MAGIC) {
                    uint32_t conv = *(uint32_t*)(buffer + 4);
                    uint16_t name_len = *(uint16_t*)(buffer + 8);
                    std::string filename(buffer + 10, name_len);
                    std::lock_guard<std::mutex> lock(mapMutex);
                    if (convFiles.find(conv) == convFiles.end()) {
                        std::ofstream file("recv_conv_" + std::to_string(conv) + "_" + filename, std::ios::binary);
                        if (file.is_open()) {
                            convFiles[conv] = std::move(file);
                            ikcpcb* kcp = ikcp_create(conv, this);
                            ikcp_wndsize(kcp, 128, 128);
                            ikcp_nodelay(kcp, 1, 10, 2, 1);
                            convKCP[conv] = kcp;
                            printf("启动程序进程");
                            convThreads[conv] = std::thread(&KCPReceiver::processConv, this, conv);
                        }
                    }
                } else if (magic == DATA_MAGIC) {
                    uint32_t conv = *(uint32_t*)(buffer + 4);
                    char* kcp_data = buffer + 8;
                    int kcp_len = recv_len - 8;
                    std::lock_guard<std::mutex> lock(queueMutex);
                    if (convQueue.find(conv) != convQueue.end()) {
                        convQueue[conv].push(std::make_pair(kcp_data, kcp_len));
                    }
                }
            }
        }
    }

    void processConv(uint32_t conv) {
        ikcpcb* kcp = convKCP[conv];
        std::ofstream& file = convFiles[conv];
        while (running) {
            std::pair<char*, int> packet;
            {
                std::lock_guard<std::mutex> lock(queueMutex);
                if (!convQueue[conv].empty()) {
                    packet = convQueue[conv].front();
                    convQueue[conv].pop();
                } else {
                    // 等待数据包
                    continue;
                }
            }
            ikcp_input(kcp, packet.first, packet.second);
            ikcp_update(kcp, ikcp_getms());
            char app_data[1024];
            int recv_len = ikcp_recv(kcp, app_data, 1024);
            if (recv_len > 0) {
                file.write(app_data, recv_len);
            } else if (recv_len < 0) {
                // 处理错误
            }
            if (ikcp_check(kcp, ikcp_getms())) {
                ikcp_release(kcp);
                convKCP.erase(conv);
                convThreads.erase(conv);
                file.close();
                convFiles.erase(conv);
                return;
            }
        }
    }

    int sockfd;
    std::thread receiveThread;
    std::map<uint32_t, std::queue<std::pair<char*, int>>> convQueue;
    std::map<uint32_t, ikcpcb*> convKCP;
    std::map<uint32_t, std::thread> convThreads;
    std::map<uint32_t, std::ofstream> convFiles;
    std::mutex queueMutex;
    std::mutex mapMutex;
    bool running;
};

int main() {
    KCPReceiver receiver;
    receiver.start();
    // 等待传输完成
    // ...
    receiver.stop();
    return 0;
}